Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add sort commands #357

Merged
merged 19 commits into from
Jul 28, 2024
Merged

Conversation

haiyang426
Copy link
Contributor

@haiyang426 haiyang426 commented Jun 21, 2024

添加了 sort 命令 和 一些测试案例
SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern]] [ASC | DESC] [ALPHA] [STORE destination]

image

Summary by CodeRabbit

  • 新功能

    • 引入 SortCmd 类,提供多种排序选项,包括升序、降序、字母排序、限制等。实现对列表、集合和有序集合的数据排序功能。
  • Bug 修复

    • 修复 CmdDebugSegfault::DoCmd 方法,添加空指针赋值检查。
  • 测试

    • 新增与排序操作相关的测试用例,验证排序、获取、存储元素和结果。
  • Chores

    • 在 GitHub Actions 工作流文件中,为 go test 命令添加15分钟的超时设置。
    • test_on_ubuntu 任务的 run 步骤之前添加 ulimit -n 4096

Copy link

coderabbitai bot commented Jun 21, 2024

Walkthrough

这次更新引入了一个新的 SortCmd 类,它提供了基于多种标准的数据排序功能,包括升序、降序、字母排序、限制等。还在不同的数据类型如列表、集合和有序集合中实现了排序功能,并处理了相应的键值操作。此外,还对现有代码进行了小幅修改和优化。

Changes

文件路径 变更摘要
src/cmd_admin.cc 添加了新类 SortCmd,实现了多种排序功能,并对 CmdDebugSegfault::DoCmd 进行了修改。
src/cmd_admin.h 添加了 SortCmd 类及其相关方法和成员变量声明。
src/cmd_set.cc 修改了 SCardCmd::DoCmd 方法,优化了结果处理逻辑。
src/cmd_table_manager.cc 在命令表初始化中添加了 Sort 命令。
src/cmd_zset.cc 修改了 ZRangebyscoreCmd::DoCmd 方法的变量声明和初始化。
tests/admin_test.go 添加了与 Redis 排序操作相关的测试用例。
.github/.../pikiwidb.yml 在 GitHub Actions 工作流文件中为 go test 命令添加了 15 分钟的超时时间设置。

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Client
    participant Server
    participant SortCmd

    User->>Client: 发送排序命令
    Client->>Server: 转发排序命令
    Server->>SortCmd: 调用 `SortCmd::DoCmd`
    SortCmd->Server: 执行排序操作
    Server->>Client: 返回排序结果
    Client->>User: 显示排序结果
Loading

Poem

代码之中风起云,
排序算法新添新。
列表、集合皆可排,
升降序中任意行。
功能增强效率高,
代码更新齐欢畅。


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added the ✏️ Feature New feature or request label Jun 21, 2024
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Outside diff range and nitpick comments (1)
src/cmd_admin.h (1)

177-193: 新增 SortCmd

  1. SortCmd 继承自 BaseCmd,适用于处理排序命令。
  2. DoInitialDoCmd 方法分别用于初始化和执行命令。
  3. lookupKeyByPattern 方法可能用于支持模式匹配键查找。
  4. 内部结构 RedisSortObject 用于存储排序操作的中间结果。

请检查类的设计是否符合项目的整体架构和代码风格。此外,确认这个类的实现是否满足了所有预期的功能需求。

考虑增加更多注释来解释 SortCmd 类的工作原理及其方法的具体用途,这将有助于其他开发者更好地理解和维护代码。

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 9d0cbb0 and f086ab3.

Files selected for processing (7)
  • src/base_cmd.h (1 hunks)
  • src/cmd_admin.cc (2 hunks)
  • src/cmd_admin.h (2 hunks)
  • src/cmd_set.cc (1 hunks)
  • src/cmd_table_manager.cc (1 hunks)
  • src/cmd_zset.cc (1 hunks)
  • tests/admin_test.go (1 hunks)
Additional comments not posted (11)
src/cmd_admin.h (1)

10-11: 新增头文件 <optional><variant>

这些头文件的引入是为了支持 SortCmd 类中使用 std::optionalstd::variant。请确认这些类型在其他地方没有被重复引入,以避免头文件重复包含。

src/cmd_table_manager.cc (1)

60-60: 在命令表中注册 Sort 命令

确保 Sort 命令的参数数量 -2 是正确的。这通常表示命令接受两个以上的参数,但具体数量可能会根据实际情况变化。请验证这一设置是否符合 Sort 命令的设计。

Verification successful

在命令表中注册 Sort 命令

Sort 命令的参数数量设置为 -2 是正确的。这表示该命令接受两个或更多的参数,这与 Sort 命令的设计和功能相符。

  • src/cmd_admin.cc 行 267-270: SortCmd 构造函数接受 namearity 参数,并将 arity 设置为 -2
Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# 验证 Sort 命令的参数数量设置是否正确
grep -rn "SortCmd" ./src/

Length of output: 484



Script:

#!/bin/bash
# Inspect the SortCmd constructor and usage to confirm the arity value
grep -A 5 "SortCmd::SortCmd" ./src/cmd_admin.cc

Length of output: 281

tests/admin_test.go (3)

163-186: 测试 Sort 命令的基本功能

这些测试用例检查了 Sort 命令对列表中的元素进行排序的能力。请确保测试覆盖了所有重要的边界条件和潜在的错误情况。同时,验证测试用的数据(例如列表中的元素)是否设置正确。


188-221: 测试 Sort 命令的 GetStore 选项

这些测试用例涉及到使用 GetStore 选项的更复杂场景。请检查这些选项的实现是否符合预期的行为,特别是在处理不存在的键或错误参数时的行为。


223-253: 测试 Sort 命令的 Store 功能

这个测试用例验证了 Sort 命令结合 Store 选项将排序结果存储到另一个键中的功能。确保测试检查了存储操作的正确性和结果的有效性。

src/cmd_set.cc (1)

161-165: 优化 SCard 命令的结果处理

这个更改优化了 SCard 命令的结果处理逻辑,使其能够在找不到键时也返回结果。请确保这种处理方式符合业务逻辑和用户期望。

src/base_cmd.h (1)

91-91: 新增了常量 kCmdNameSort 来表示 "sort" 命令

这个更改是为了支持新的 sort 命令,确保命令名称在整个项目中统一管理,有助于维护和后续的功能扩展。

src/cmd_admin.cc (3)

267-268: 新增 SortCmd 类构造函数

此构造函数正确地初始化了基类 BaseCmd,设置了命令名称、参数数量、命令标志和ACL类别。这是标准的初始化过程,确保了命令的基本属性被正确设置。


270-272: SortCmd::DoInitial 方法的实现

此方法设置了命令的关键字,这是处理排序命令的第一步。此实现符合预期的初始化行为,没有发现逻辑错误。


441-474: SortCmd::lookupKeyByPattern 方法的实现

此方法用于根据模式查找键值,逻辑正确处理了模式匹配和字段提取。此方法是 sort 命令功能的重要组成部分,正确地实现了预期功能。

src/cmd_zset.cc (1)

367-369: 优化布尔变量的声明和初始化

ZRangebyscoreCmd::DoCmd 方法中,布尔型变量 left_closeright_closewith_scores 被分别声明并初始化为 true。这种分开声明的方式增加了代码的可读性和可维护性。

src/cmd_admin.cc Outdated
Comment on lines 275 to 439
storage::Status s = PSTORE.GetBackend(client->GetCurrentDB())->GetStorage()->SMembers(client->Key(), &ret);
} else if (types[0] == "zset") {
std::vector<storage::ScoreMember> score_members;
storage::Status s =
PSTORE.GetBackend(client->GetCurrentDB())->GetStorage()->ZRange(client->Key(), 0, -1, &score_members);
char buf[32];
int64_t score_len = 0;

for (auto& c : score_members) {
ret.emplace_back(c.member);
}
} else {
client->SetRes(CmdRes::kErrOther, "WRONGTYPE Operation against a key holding the wrong kind of value");
return;
}

std::vector<RedisSortObject> sort_ret(ret.size());
for (size_t i = 0; i < ret.size(); ++i) {
sort_ret[i].obj = ret[i];
}

if (!dontsort) {
for (size_t i = 0; i < ret.size(); ++i) {
std::string byval;
if (!sortby.empty()) {
auto lookup = lookupKeyByPattern(client, sortby, ret[i]);
if (!lookup.has_value()) {
byval = ret[i];
} else {
byval = std::move(lookup.value());
}
} else {
byval = ret[i];
}

if (alpha) {
sort_ret[i].u = byval;
} else {
// auto double_byval = pstd::String2d()
double double_byval;
if (pstd::String2d(byval, &double_byval)) {
sort_ret[i].u = double_byval;
} else {
client->SetRes(CmdRes::kErrOther, "One or more scores can't be converted into double");
return;
}
}
}

std::sort(sort_ret.begin(), sort_ret.end(), [&alpha, &desc](const RedisSortObject& a, const RedisSortObject& b) {
if (alpha) {
std::string score_a = std::get<std::string>(a.u);
std::string score_b = std::get<std::string>(b.u);
return !desc ? score_a < score_b : score_a > score_b;
} else {
double score_a = std::get<double>(a.u);
double score_b = std::get<double>(b.u);
return !desc ? score_a < score_b : score_a > score_b;
}
});

size_t sort_size = sort_ret.size();

count = count >= 0 ? count : sort_size;
offset = (offset >= 0 && offset < sort_size) ? offset : sort_size;
count = (offset + count < sort_size) ? count : sort_size - offset;

size_t m_start = offset;
size_t m_end = offset + count;

ret.clear();
if (get_patterns.empty()) {
get_patterns.emplace_back("#");
}

for (; m_start < m_end; m_start++) {
for (const std::string& pattern : get_patterns) {
std::optional<std::string> val = lookupKeyByPattern(client, pattern, sort_ret[m_start].obj);
if (val.has_value()) {
ret.push_back(val.value());
} else {
ret.emplace_back("");
}
}
}
}

if (store_key.empty()) {
client->AppendStringVector(ret);
} else {
// std::vector<std::string> list_values(client->argv_.begin() + 2, client->argv_.end());
uint64_t reply_num = 0;
storage::Status s = PSTORE.GetBackend(client->GetCurrentDB())->GetStorage()->RPush(store_key, ret, &reply_num);
if (s.ok()) {
client->AppendInteger(reply_num);
} else {
client->SetRes(CmdRes::kSyntaxErr, "rpush cmd error");
}
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SortCmd::DoCmd 方法的复杂实现

这个方法实现了 sort 命令的核心功能,包括解析命令参数和执行排序操作。代码较长且包含多个分支,建议在未来的版本中考虑将其拆分成更小的函数,以提高代码的可读性和可维护性。

- void SortCmd::DoCmd(PClient* client) {
+ // 建议拆分此方法,将参数解析、排序逻辑、结果存储等分别封装到独立的私有方法中。

Committable suggestion was skipped due to low confidence.

@AlexStocks
Copy link
Contributor

ci 失败,把 go test 时间改为 15 分钟

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


ci fails, change go test time to 15 minutes

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between f086ab3 and bbe6624.

Files selected for processing (1)
  • .github/workflows/pikiwidb.yml (2 hunks)
Files skipped from review due to trivial changes (1)
  • .github/workflows/pikiwidb.yml

@haiyang426 haiyang426 closed this Jun 23, 2024
@haiyang426 haiyang426 reopened this Jun 23, 2024
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between bbe6624 and b064f70.

Files selected for processing (1)
  • src/cmd_admin.cc (2 hunks)
Additional comments not posted (3)
src/cmd_admin.cc (3)

267-268: 构造函数 SortCmd::SortCmd 看起来不错。

代码遵循了其他命令类的初始化模式。


270-273: 方法 SortCmd::DoInitial 看起来不错。

代码遵循了其他命令类的初始化模式。


437-470: 方法 SortCmd::lookupKeyByPattern 看起来不错。

代码结构良好,并使用了可选值来处理查找可能失败的情况。

src/cmd_admin.cc Outdated
Comment on lines 275 to 434
if (types[0] == "list") {
storage::Status s = PSTORE.GetBackend(client->GetCurrentDB())->GetStorage()->LRange(client->Key(), 0, -1, &ret);
} else if (types[0] == "set") {
storage::Status s = PSTORE.GetBackend(client->GetCurrentDB())->GetStorage()->SMembers(client->Key(), &ret);
} else if (types[0] == "zset") {
std::vector<storage::ScoreMember> score_members;
storage::Status s =
PSTORE.GetBackend(client->GetCurrentDB())->GetStorage()->ZRange(client->Key(), 0, -1, &score_members);
char buf[32];
int64_t score_len = 0;

for (auto& c : score_members) {
ret.emplace_back(c.member);
}
} else {
client->SetRes(CmdRes::kErrOther, "WRONGTYPE Operation against a key holding the wrong kind of value");
return;
}

std::vector<RedisSortObject> sort_ret(ret.size());
for (size_t i = 0; i < ret.size(); ++i) {
sort_ret[i].obj = ret[i];
}

if (!dontsort) {
for (size_t i = 0; i < ret.size(); ++i) {
std::string byval;
if (!sortby.empty()) {
auto lookup = lookupKeyByPattern(client, sortby, ret[i]);
if (!lookup.has_value()) {
byval = ret[i];
} else {
byval = std::move(lookup.value());
}
} else {
byval = ret[i];
}

if (alpha) {
sort_ret[i].u = byval;
} else {
double double_byval;
if (pstd::String2d(byval, &double_byval)) {
sort_ret[i].u = double_byval;
} else {
client->SetRes(CmdRes::kErrOther, "One or more scores can't be converted into double");
return;
}
}
}

std::sort(sort_ret.begin(), sort_ret.end(), [&alpha, &desc](const RedisSortObject& a, const RedisSortObject& b) {
if (alpha) {
std::string score_a = std::get<std::string>(a.u);
std::string score_b = std::get<std::string>(b.u);
return !desc ? score_a < score_b : score_a > score_b;
} else {
double score_a = std::get<double>(a.u);
double score_b = std::get<double>(b.u);
return !desc ? score_a < score_b : score_a > score_b;
}
});

size_t sort_size = sort_ret.size();

count = count >= 0 ? count : sort_size;
offset = (offset >= 0 && offset < sort_size) ? offset : sort_size;
count = (offset + count < sort_size) ? count : sort_size - offset;

size_t m_start = offset;
size_t m_end = offset + count;

ret.clear();
if (get_patterns.empty()) {
get_patterns.emplace_back("#");
}

for (; m_start < m_end; m_start++) {
for (const std::string& pattern : get_patterns) {
std::optional<std::string> val = lookupKeyByPattern(client, pattern, sort_ret[m_start].obj);
if (val.has_value()) {
ret.push_back(val.value());
} else {
ret.emplace_back("");
}
}
}
}

if (store_key.empty()) {
client->AppendStringVector(ret);
} else {
uint64_t reply_num = 0;
storage::Status s = PSTORE.GetBackend(client->GetCurrentDB())->GetStorage()->RPush(store_key, ret, &reply_num);
if (s.ok()) {
client->AppendInteger(reply_num);
} else {
client->SetRes(CmdRes::kSyntaxErr, "rpush cmd error");
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

方法 SortCmd::DoCmd 实现复杂,建议重构。

该方法实现了 sort 命令的核心功能,包括解析命令参数和执行排序操作。代码较长且包含多个分支,建议将其拆分成更小的函数,以提高代码的可读性和可维护性。

- void SortCmd::DoCmd(PClient* client) {
+ // 建议拆分此方法,将参数解析、排序逻辑、结果存储等分别封装到独立的私有方法中。

Committable suggestion was skipped due to low confidence.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between b064f70 and 990d4bd.

Files selected for processing (1)
  • .github/workflows/pikiwidb.yml (2 hunks)
Additional comments not posted (2)
.github/workflows/pikiwidb.yml (2)

46-47: 更改已批准

增加 ulimit -n 4096go test -timeout 15m 是为了确保在 macOS 上进行测试时有足够的文件描述符限制和测试时间。


71-71: 更改已批准

go test 的超时时间增加到 15 分钟,以确保测试有足够的时间完成。

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 990d4bd and 789bbac.

Files selected for processing (1)
  • .github/workflows/pikiwidb.yml (2 hunks)
Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/pikiwidb.yml

src/cmd_admin.cc Outdated
storage::Status s = PSTORE.GetBackend(client->GetCurrentDB())->GetStorage()->LRange(client->Key(), 0, -1, &ret);
} else if (types[0] == "set") {
storage::Status s = PSTORE.GetBackend(client->GetCurrentDB())->GetStorage()->SMembers(client->Key(), &ret);
} else if (types[0] == "zset") {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

zset本身具有有序性,再进行排序会不会不合适

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

zset本身具有有序性,再进行排序会不会不合适

我看sort 命令支持zset数据类型 应该是想通过关联其他数据进行排序,就是by后面的pattern。例如:sort myzset by user*

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

有道理

src/cmd_admin.cc Outdated Show resolved Hide resolved
client->SetRes(CmdRes::kErrOther, "WRONGTYPE Operation against a key holding the wrong kind of value");
return;
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

要是获取数据失败了怎么办,这里可以根据status加一个错误处理

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

要是获取数据失败了怎么办,这里可以根据status加一个错误处理

嗯嗯,感谢,我再修改一下

@haiyang426
Copy link
Contributor Author

ref #30

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


ref #30

src/cmd_admin.cc Outdated
storage::Status s = PSTORE.GetBackend(client->GetCurrentDB())->GetStorage()->LRange(client->Key(), 0, -1, &ret);
} else if (types[0] == "set") {
storage::Status s = PSTORE.GetBackend(client->GetCurrentDB())->GetStorage()->SMembers(client->Key(), &ret);
} else if (types[0] == "zset") {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

有道理

return;
}
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

293行到324行的代码主要是做命令行的解析,挪到doinitial会不会好一些

@saz97
Copy link

saz97 commented Jul 4, 2024

不仅加了新的feat,还附上了新的测试,很不错的pr

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


Not only new features are added, but also new tests are attached. It’s a very good PR.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Outside diff range and nitpick comments (2)
src/cmd_admin.h (2)

Line range hint 181-336:
方法 SortCmd::DoInitial 实现复杂,建议重构。

该方法实现了 sort 命令的参数解析。代码较长且包含多个分支,建议将其拆分成更小的函数,以提高代码的可读性和可维护性。

- void SortCmd::DoInitial(PClient* client) {
+ // 建议拆分此方法,将参数解析逻辑分别封装到独立的私有方法中。

Line range hint 338-420:
方法 SortCmd::DoCmd 实现复杂,建议重构。

该方法实现了 sort 命令的核心功能,包括排序和结果存储。代码较长且包含多个分支,建议将其拆分成更小的函数,以提高代码的可读性和可维护性。

- void SortCmd::DoCmd(PClient* client) {
+ // 建议拆分此方法,将排序逻辑和结果存储分别封装到独立的私有方法中。
Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 789bbac and af9a8ce.

Files selected for processing (2)
  • src/cmd_admin.cc (2 hunks)
  • src/cmd_admin.h (2 hunks)
Additional comments not posted (6)
src/cmd_admin.h (3)

177-180: LGTM!

构造函数初始化 SortCmd 类,无问题。


Line range hint 422-455:
LGTM!

方法 lookupKeyByPattern 正确处理了按模式查找键的逻辑,无问题。


Line range hint 457-467:
LGTM!

方法 InitialArgument 初始化了排序命令的参数,无问题。

src/cmd_admin.cc (3)

267-269: LGTM!

构造函数初始化 SortCmd 类,无问题。


422-455: LGTM!

方法 lookupKeyByPattern 正确处理了按模式查找键的逻辑,无问题。


457-467: LGTM!

方法 InitialArgument 初始化了排序命令的参数,无问题。

src/cmd_admin.cc Outdated
Comment on lines 338 to 420
void SortCmd::DoCmd(PClient* client) {
std::vector<RedisSortObject> sort_ret(ret.size());
for (size_t i = 0; i < ret.size(); ++i) {
sort_ret[i].obj = ret[i];
}

if (!dontsort) {
for (size_t i = 0; i < ret.size(); ++i) {
std::string byval;
if (!sortby.empty()) {
auto lookup = lookupKeyByPattern(client, sortby, ret[i]);
if (!lookup.has_value()) {
byval = ret[i];
} else {
byval = std::move(lookup.value());
}
} else {
byval = ret[i];
}

if (alpha) {
sort_ret[i].u = byval;
} else {
double double_byval;
if (pstd::String2d(byval, &double_byval)) {
sort_ret[i].u = double_byval;
} else {
client->SetRes(CmdRes::kErrOther, "One or more scores can't be converted into double");
return;
}
}
}

std::sort(sort_ret.begin(), sort_ret.end(), [this](const RedisSortObject& a, const RedisSortObject& b) {
if (this->alpha) {
std::string score_a = std::get<std::string>(a.u);
std::string score_b = std::get<std::string>(b.u);
return !this->desc ? score_a < score_b : score_a > score_b;
} else {
double score_a = std::get<double>(a.u);
double score_b = std::get<double>(b.u);
return !this->desc ? score_a < score_b : score_a > score_b;
}
});

size_t sort_size = sort_ret.size();

count = count >= 0 ? count : sort_size;
offset = (offset >= 0 && offset < sort_size) ? offset : sort_size;
count = (offset + count < sort_size) ? count : sort_size - offset;

size_t m_start = offset;
size_t m_end = offset + count;

ret.clear();
if (get_patterns.empty()) {
get_patterns.emplace_back("#");
}

for (; m_start < m_end; m_start++) {
for (const std::string& pattern : get_patterns) {
std::optional<std::string> val = lookupKeyByPattern(client, pattern, sort_ret[m_start].obj);
if (val.has_value()) {
ret.push_back(val.value());
} else {
ret.emplace_back("");
}
}
}
}

if (store_key.empty()) {
client->AppendStringVector(ret);
} else {
uint64_t reply_num = 0;
storage::Status s = PSTORE.GetBackend(client->GetCurrentDB())->GetStorage()->RPush(store_key, ret, &reply_num);
if (s.ok()) {
client->AppendInteger(reply_num);
} else {
client->SetRes(CmdRes::kErrOther, s.ToString());
}
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

方法 SortCmd::DoCmd 实现复杂,建议重构。

该方法实现了 sort 命令的核心功能,包括排序和结果存储。代码较长且包含多个分支,建议将其拆分成更小的函数,以提高代码的可读性和可维护性。

- void SortCmd::DoCmd(PClient* client) {
+ // 建议拆分此方法,将排序逻辑和结果存储分别封装到独立的私有方法中。

Committable suggestion was skipped due to low confidence.

src/cmd_admin.cc Outdated
Comment on lines 270 to 336
bool SortCmd::DoInitial(PClient* client) {
InitialArgument();
client->SetKey(client->argv_[1]);
size_t argc = client->argv_.size();
for (int i = 2; i < argc; ++i) {
int leftargs = argc - i - 1;
if (strcasecmp(client->argv_[i].data(), "asc") == 0) {
desc = 0;
} else if (strcasecmp(client->argv_[i].data(), "desc") == 0) {
desc = 1;
} else if (strcasecmp(client->argv_[i].data(), "alpha") == 0) {
alpha = 1;
} else if (strcasecmp(client->argv_[i].data(), "limit") == 0 && leftargs >= 2) {
if (pstd::String2int(client->argv_[i + 1], &offset) == 0 || pstd::String2int(client->argv_[i + 2], &count) == 0) {
client->SetRes(CmdRes::kSyntaxErr);
return false;
}
i += 2;
} else if (strcasecmp(client->argv_[i].data(), "store") == 0 && leftargs >= 1) {
store_key = client->argv_[i + 1];
i++;
} else if (strcasecmp(client->argv_[i].data(), "by") == 0 && leftargs >= 1) {
sortby = client->argv_[i + 1];
if (sortby.find('*') == std::string::npos) {
dontsort = 1;
}
i++;
} else if (strcasecmp(client->argv_[i].data(), "get") == 0 && leftargs >= 1) {
get_patterns.push_back(client->argv_[i + 1]);
i++;
} else {
client->SetRes(CmdRes::kSyntaxErr);
return false;
}
}

Status s;
s = PSTORE.GetBackend(client->GetCurrentDB())->GetStorage()->LRange(client->Key(), 0, -1, &ret);
if (s.ok()) {
return true;
} else if (!s.IsNotFound()) {
client->SetRes(CmdRes::kErrOther, s.ToString());
return false;
}

s = PSTORE.GetBackend(client->GetCurrentDB())->GetStorage()->SMembers(client->Key(), &ret);
if (s.ok()) {
return true;
} else if (!s.IsNotFound()) {
client->SetRes(CmdRes::kErrOther, s.ToString());
return false;
}

std::vector<storage::ScoreMember> score_members;
s = PSTORE.GetBackend(client->GetCurrentDB())->GetStorage()->ZRange(client->Key(), 0, -1, &score_members);
if (s.ok()) {
for (auto& c : score_members) {
ret.emplace_back(c.member);
}
return true;
} else if (!s.IsNotFound()) {
client->SetRes(CmdRes::kErrOther, s.ToString());
return false;
}
client->SetRes(CmdRes::kErrOther, "Unknown Type");
return false;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

方法 SortCmd::DoInitial 实现复杂,建议重构。

该方法实现了 sort 命令的参数解析。代码较长且包含多个分支,建议将其拆分成更小的函数,以提高代码的可读性和可维护性。

- void SortCmd::DoInitial(PClient* client) {
+ // 建议拆分此方法,将参数解析逻辑分别封装到独立的私有方法中。

Committable suggestion was skipped due to low confidence.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between af9a8ce and ccbf94c.

Files selected for processing (1)
  • src/cmd_admin.cc (2 hunks)
Files skipped from review as they are similar to previous changes (1)
  • src/cmd_admin.cc

@haiyang426 haiyang426 requested a review from saz97 July 8, 2024 08:19
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between ccbf94c and 648c6bd.

Files selected for processing (2)
  • src/cmd_admin.cc (2 hunks)
  • src/cmd_admin.h (2 hunks)
Files skipped from review as they are similar to previous changes (1)
  • src/cmd_admin.cc
Additional comments not posted (7)
src/cmd_admin.h (7)

10-11: 引入新的头文件是正确的

新引入的 <optional><variant>SortCmd 类所需的,没有问题。


177-204: SortCmd 类声明正确

SortCmd 类的声明符合标准实践,使用 std::optionalstd::variant 也很合适。


179-179: 构造函数定义正确

构造函数 SortCmd(const std::string& name, int16_t arity) 定义简洁明了,符合预期的命令类模式。


182-182: DoInitial 方法定义正确

DoInitial 方法重写了基类方法,方法签名正确,符合基类接口。


185-185: DoCmd 方法定义正确

DoCmd 方法重写了基类方法,方法签名正确,符合基类接口。


188-188: lookupKeyByPattern 方法定义正确

lookupKeyByPattern 方法返回 std::optional<std::string>,使用 std::optional 很适合用于可能找到也可能找不到匹配键的方法。


187-187: InitialArgument 方法定义正确

InitialArgument 方法没有参数,可能用于初始化命令参数。没有发现问题。

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 648c6bd and a01c008.

Files selected for processing (1)
  • src/cmd_admin.cc (2 hunks)
Files skipped from review as they are similar to previous changes (1)
  • src/cmd_admin.cc

@Tangruilin Tangruilin requested review from Tangruilin and removed request for saz97 July 27, 2024 13:46
@AlexStocks AlexStocks merged commit 110fa8c into OpenAtomFoundation:unstable Jul 28, 2024
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
✏️ Feature New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants